VA_ARG - VA_START

            #include <varargs.h>           требуется          для
                                           совместимости с UNIX V.
            
            #include<stdarg.h>             требуется          для
                                           совместимости       со
                                           стандартом   ANSI   C.
            
            void  va_start(arg-ptr);       макро   для   установки
                                           arg-ptr    к     началу
                                           списка   необязательных
                                           аргументов      (только
                                           версия <varargs.h>).
            
            void va_start(arg-ptr, prev-param);
                                           макро   для   установки
                                           arg-ptr к началу списка
                                           необязательных    аргу-
                                           ментов  (только  версия
                                           <stdarg.h>).
            
            type va_start(arg-ptr, type);  макро  для  возвращения
                                           текущего аргумента
            
            void va_arg(arg-ptr);          макро для переустановки
                                           arg-ptr
            
            va_list arg-ptr;               указатель   на   список
                                           аргументов;
            type                           тип       возвращаемого
                                           аргумента;
            prev-param                     параметр, предшедствую-
                                           щий             первому
                                           необязательному   аргу-
                                           менту  (только   версия
                                           <stdarg.h>).
            
            va_alist                       имя параметра для вызы-
                                           ваемой  функции (только
                                           версия <varargs.h>).
            
            va_dcl                         объявление     va_alist
                                           (только          версия
                                           <varargs.h>).
            

Описание.
Макро va_start, va_arg, va_end обеспечивают способ доступа к аргументам функции, когда она принимает переменное количество аргументов.
Доступны 2 версии макро: макро, объявленные в <varargs.h>, которые совместимы с определением системы UNIX 5, и макро, объявленные в <stdarg.h>, которые приведены в соответствии со стандартом ANSI C.
Обе версии макро предполагают, что функция принимает фиксированное число требуемых аргументов, следующее за переменным числом необязательных аргументов. Требуемые аргументы объявлены как необязательные параметры для функций и могут быть доступны через имена параметров. Необязательные аргументы доступны через макро <varargs.h> или <stdarg.h>, которые устанавливают указатель на первый необязательный аргумент в списке аргументов; возвращают аргументы из списка и переустанавливают указатель, когда обработка аргументов завершена.
Макро системы UNIX 5, объявленные в <varargs.h>, используются как показано ниже.
1. Любые требуемые параметры для функции могут быть объявлены обычным способом как параметры.
2. Последний параметр для функции представляет список необязательных аргументов. Этот параметр должен быть назван va_alist (не перепутайте его с va_list, который объявлен как тип va_alist).
3. Макро va_dcl появляется после объявления функции и перед открытой левой скобкой функции. Эта макро объявляется как полное описание параметра va_alist, оканчивающегося точкой с запятой, однако, за va_dcl не может идти точка с запятой.
4. Внутри функции макро va_start устанавливает arg-ptr к началу списка необязательных параметров, который передается функции. Макро va_start должна использоваться перед va_arg , используемой в первый раз. Аргумент arg-ptr должен иметь тип va_list.
5. Макро va_arg выполняет следующее:
* возвращает значение заданного типа type из того расположения, которое определяется по аргументу arg-ptr;
* увеличивает arg-ptr, чтобы указать на следующий аргумент в списке, используя размер type для определения начала расположения следующего аргумента.
Внутри функций макро va_arg может использоваться любое количество раз, чтобы возвратить требуемые аргументы из списка.
6. После возвращения всех аргументов va_end устанавливает указатель в NULL.

Макро, предлагаемые стандартом ANSI C и объявленные в <stdarg.h>, незначительно отличаются от макро, которые объявлены в <varargs.h>.
1. Все требуемые аргументы для функции объявляются как параметры. Макро va_dcl не используется вместе с макро <stdarg.h>.
2. Макро va_start устанавливает arg-ptr на первый необязательный аргумент из списка аргументов, который передается функции. Аргумент arg-prt должен иметь тип va_list. Аргумент prev-param является именем требуемого параметра, непосредственно предшествующего первому необязательному параметру из списка аргументов. Макро va_start должна быть использована перед va_arg, используемой в первый раз.
3. Макро va_arg выполняет следующее:
* возвращает значение типа type из того расположения, которое определяется по аргументу arg-ptr.
* чтобы указать на следующий аргумент в списке, она увеличивает arg-ptr и использует размер type для определения начала расположения следующего аргумента.
Внутри функций макро va_arg может использоваться любое количество раз, чтобы возвратить требуемые аргументы из списка.
4. После возвращения всех аргументов, va_end переустанавливает указатель в NULL.

Возвращаемое значение.
Макро va_arg возвращает текущий аргумент; va_start и va_end значений не возвращают.

Пример:
Ниже приводится листинг программы, использующей <varargs.h> для совместимости с UNIX V.

            #include <stdio.h>
            #include <varargs.h>
            
            main()
            {
                   int n;
                   .
                   .
                   .
               /* вызывается функция 4-х  аргументов;  последний  аргумент
         задается равным -1, чтобы отметить конец списка аргументов */
            
                   n = average(2, 3, 4, -1);
            printf("Average is: %d\n", n);
                   .
                   .
                   .
               /*  вызывается  функция 5-ти аргументов; последний аргумент
         задается равным -1, чтобы отметить конец списка аргументов */
            
                   n = average(5, 7, 9, 11, -1);
            printf("Average is: %d\n", n);
            }
            
            average(va_alist)
            va_dcl
              {
                 int i = 0, count = 0, sum = 0;
                 va_list arg_marker;
            
                 va_start(arg_marker);
            
               /* возвращение аргументов и прибавление к sum, пока не вст-
         ретится последний аргумент -1. */
      
             for (; (i = va_arg(arg_marker, int)) >= 0;
                         sum+=i, count++)
                              ;
                 return (count ? (sum/count) : count);
              }

Аналогичная программа, перезаписанная для совместимости со стандартом ANSI C.

            #include <stdio.h>
            #include <stdarg.h>
            
            main()
            {
                   int n;
                   .
                   .
                   .
               /* вызывается функция 4-х  аргументов;  последний  аргумент
         задается равным -1, чтобы отметить конец списка аргументов */
            
                   n = average(2, 3, 4, -1);
            printf("Average is: %d\n", n);
                   .
                   .
                   .
               /*  вызывается  функция 5-ти аргументов; последний аргумент
         задается равным -1, чтобы отметить конец списка аргументов */
            
                   n = average(5, 7, 9, 11, -1);
            printf("Average is: %d\n", n);
            }
            
            average(first)
            int first;
              {
                 int i = 0, count = 0, sum;
                 va_list arg_marker;
            
                 va_start(arg_marker, first);
            
               /* первый  аргумент  прибавляется  к  sum  и  увеличивается
         count; если первый аргумент равен -1, происходит возврат */
            
                 if (first != -1)
                      sum = first;
                 else
                      return (0);
                 count++;
               /*  возвращение  дополнительных  аргументов и прибавление к
         sum, пока не встретится последний аргумент -1. */
            
                 for (; (i = va_arg(arg_marker, int)) >= 0;
                         sum+=i, count++)
                              ;
                 return (sum/count);
              }
 
Hosted by uCoz